/*
 * Copyright (c) 1999 by Visa International Service Association, all rights reserved.
 * Visa is a registered trademark of Visa International Service Association. This
 * software is the property of Visa International Service Association and is protected
 * under the copyright, trade secret and confidentiality laws of the United States
 * and other countries, including each of the countries in which it is licensed.
 */

// $Date:    01/18/99 3:34p $
// $Author:  Rick Dabir $
// $Revised: 12/31/99   $

package visa.openplatform;

import javacard.framework.*;
import org.globalplatform.*;
import com.wk.javacard.vnative.VN;

/**
 * The OPSystem class exposes a subset of the behavior of the Card Manager to the outside world. It extends
 * the functionality of the JCRE 2.1 APIs by providing card management services to applets. It implements and
 * enforces a Card Issuer's security policies. This class provides the functionality of a runtime environment
 * running at the JCRE 'system' (privileged) context. The details of the JCRE 'system' context implementation
 * are left to the implementer. This class's public interface is composed of static methods visible to all
 * applets importing the openplatform package. This is a 'singleton' class (only one instance is created for
 * the lifetime of the card).
 */

public final class OPSystem {

    /**
	 * The applet is not present on the card or is marked as a deleted ROM entry: DELETED = 0x00.
	 */
	//public static final byte APPLET_LOGICALLY_DELETED = (byte)0x00;

    /**
	 * The applet has benn loaded onto the card: LOADED = 0x01
	 */
 //	public static final byte APPLET_LOADED = (byte)0x01;    // Not defined in 2.0.1 Spec

    /**
	 * Application life-cycle state indicating the application is INSTALLED = 0x03.
	 * The applet has been instantiated and has completed the install() method.
	 */
	public static final byte APPLET_INSTALLED = (byte)0x03;

	/**
	 * Application life-cycle state indicating the application is SELECTABLE = 0x07.
	 * The applet has reached the SELECTABLE state and is available to receive SELECT commands.
	 */
	public static final byte APPLET_SELECTABLE = (byte)0x07;

	/**
	 * Application life-cycle state indicating the application is PERSONALIZED = 0x0F.
	 * The applet has been loaded with applet-specific data.
	 */
	public static final byte APPLET_PERSONALIZED = (byte)0x0F;

	/**
	 * Application life-cycle state indicating the application is BLOCKED = 0x7F.
	 * This state is the result of an on-card or off-card event.
	 */
	public static final byte APPLET_BLOCKED = (byte)0x7F;

	/**
	 * Application life-cycle state indicating the application is LOCKED = 0xFF.
	 * This state results from a Card Manager internal invoked or Card Issuer invoked action:
	 * LOCKED = 0xFF.
	 */
  	public static final byte APPLET_LOCKED = (byte)0xFF;


	/**
	 * The executable load file life-cycle state indicating the package is LOADED = 0x01.
	 * The package in a CAP file has been loaded onto a card.
	 */
	public static final byte PACKAGE_LOADED = (byte)0x01;

	/**
	 * The executable load file life-cycle state indicating the package is
	 * LOGICALLY_DELETED = 0x00. The package is not present on the card or
	 * is marked as a deleted ROM entry.

	 */
	//public static final byte PACKAGE_LOGICALLY_DELETED = (byte)0x00;


	/**
	 * The OPSystem is operational on the card: READY = 0x01.
	 */
	public static final byte CARD_OP_READY = (byte)0x01;

	/**
	 * The state is an administrative card production state: INITIALIZED = 0x07.
	 */
	//public static final byte CARD_INITIALIZED = (byte)0x07;     // aka CARD_CM_PERSONALIZED
	public static final byte INITIALIZED = (byte)0x07;     // aka CARD_CM_PERSONALIZED

	/**
	 * The card is ready for issuance or has been issued to a Cardholder: SECURED = 0x0F.
	 */
	public static final byte CARD_SECURED = (byte)0x0F;

	/**
	 * The Card Manager has locked the card because it detected an on-card security threat: CM_LOCKED = 0x7F.
	 */
	//public static final byte CARD_CM_LOCKED = (byte)0x7F;
	public static final byte CARD_LOCKED = (byte)0x7F;

	/**
	 * The card is no longer operational: TERMINATED = 0xFF.
	 */
   	//public static final byte CARD_TERMINATED = (byte)0xFF;


	// The following definitions from OP Card 1.0 existed on OP.class

	/**
	 * APDU Class byte for OP APDUs
     */
    static final byte CLA_OP = (byte) 0x80;      // proprietary command
    static final byte CLA_OP_ENC = (byte) 0x84;  // MAC and/or encryption

    /**
     * Instruction value for the APDU Append Record: 0xE2
     */
    static final byte INS_OP_APPEND_RECORD = (byte) 0xE2;

    /**
     * Instruction value for the APDU Delete: 0xE4
     */
    static final byte INS_OP_DELETE = (byte) 0xE4;

    /**
     * Instruction value for the APDU Get Data: 0xCA
     */
    static final byte INS_OP_GET_DATA = (byte) 0xCA;

    /**
     * Instruction value for the APDU Get Status: 0xF2
     */
    static final byte INS_OP_GET_STATUS = (byte) 0xF2;

    /**
     * Instruction value for the APDU Install: 0xE6
     */
    static final byte INS_OP_INSTALL = (byte) 0xE6;

    /**
     * Instruction value for the APDU Load: 0xE6
     */
    static final byte INS_OP_LOAD = (byte) 0xE8;

    /**
     * Instruction value for the APDU Pin Change: 0x24
     */
    static final byte INS_OP_PIN_CHANGE = (byte) 0x24;

    /**
     * Instruction value for the APDU Put Data: 0xDA
     */
    static final byte INS_OP_PUT_DATA = (byte) 0xDA;

    /**
     * Instruction value for the APDU Put Key: 0xD8
     */
    static final byte INS_OP_PUT_KEY = (byte) 0xD8;

    /**
     * Instruction value for the APDU Read Record: 0xB2
     */
    static final byte INS_OP_READ_RECORD = (byte) 0xB2;

    /**
     * Instruction value for the APDU Set Status: 0xF0
     */
    static final byte INS_OP_SET_STATUS = (byte) 0xF0;

    /**
     * Instruction value for the APDU Update Binary: 0xD6
     */
    static final byte INS_OP_UPDATE_BINARY = (byte) 0xD6;

    /**
     * Instruction value for the APDU Update Record: 0xDC
     */
    static final byte INS_OP_UPDATE_RECORD = (byte) 0xDC;

    /**
     * Instruction value for the APDU Initialize Update: 0x50
     */
    static final byte INS_ISO_INITIALIZE_UPDATE = (byte) 0x50;

    /**
     * Instruction value for the APDU Verify: 0x20
     */
    static final byte INS_ISO_VERIFY = (byte) 0x20;


    /**
     * P1 and P2 values
     */
    // This P1 value is used with the Set Status APDU to indicate a card status change
    static final byte P1_OP_CARD_STATUS = (byte)0x80;

    // This P1 value is used with the Set Status APDU to indicate an application status change
    static final byte P1_OP_APPLET_STATUS = (byte)0x40;

    // This P1 value is used with the Set Status APDU to indicate a file status change
    static final byte P1_OP_FILE_STATUS = (byte)0x20;

    // This P2 value is used with the Get/Put Data APDUs to retrieve/set the Card Fabrication Data
    static final short P2_OP_CARD_FABRICATION = (short)0x9F6A;

    // This P2 value is used with the Get/Put Data APDUs to retrieve/set the Module Fabrication Data
    static final short P2_OP_MODULE_FABRICATION = (short)0x9F69;

    // This P2 value is used with the Get/Put Data APDUs to retrieve/set the Card Manufacturer Data
    static final short P2_OP_CARD_MANUFACTURER = (short)0x9F68;

    // This P2 value is used with the Get/Put Data APDUs to retrieve/set the Pre-personalization Data
    static final short P2_OP_PRE_PERSONALISER = (short)0x9F67;

    // This P2 value is used with the Get/Put Data APDUs to retrieve/set the Personalization Data
    static final short P2_OP_PERSONALISER = (short)0x9F66;

    // This P2 value is used with the Get Data APDUs to retrieve the Personalization Key Data
    static final short P2_OP_APPLET_PERSONALIZATION_KEY = (short)0x9F6F;

    // This P2 value is used with the Get Data APDUs to retrieve the Application Lifecycle
    static final short P2_OP_APPLET_LIFECYCLE = (short)0x9F70;

    // This P2 value is used with the Get Data APDUs to retrieve the Card Lifecycle
    static final short P2_OP_CARD_LIFECYCLE = (short)0x9F71;

    // This P2 value is used with the Get Data APDUs to retrieve the Card Production Lifecycle
    static final short P2_OP_CARD_CPLC = (short)0x9F7F;

    static final short P2_OP_ISSUER_BIN = (short)0x0042;
    static final short P2_OP_CARD_ISSUER_DATA = (short)0x0045;

    /**
     * Application priviledges in the card registry
     */
    // Used to signify that an application is a Security Domain
    static final byte PROP_SECURITY_DOMAIN_BIT = (byte)0x80;

    // Used to signify that an application is a Security Domain with delegated management privileges
    static final byte PROP_SECURITY_DOMAIN_DAP_BIT = (byte)0x40;

    // Used to signify that an application is a Security Domain with delegated management privileges
    static final byte PROP_SECURITY_DOMAIN_DEL_BIT = (byte)0x20;

    // Used to signify that an application has card locking privileges
    static final byte PROP_CARD_LOCK_BIT = (byte)0x10;

    // Used to signify that an application has card terminating privileges
    static final byte PROP_CARD_TERMINATE_BIT = (byte)0x08;

    // Used to signify that an application is the default or implitcitly selected application
    static final byte PROP_DEFAULT_APPLET_BIT = (byte)0x04;

    // Used to signify that an application has pin setting privileges
    static final byte PROP_SET_PIN_BIT = (byte)0x02;

    /**
     * Used to signify that an entry in the card registry is a load file
     */
    static final byte PROP_LOAD_FILE_BIT = (byte)0x01;

    // Used to signify that the CardManager is requesting a SecurityDomain object from an application
    static final byte PARAM_GET_SECURITY_DOMAIN = (byte)0x01;

    // Error Status Words
    static final short NO_SPECIFIC_DIAGNOSIS_WARNING = 0x6200;
    static final short APPLICATION_INVALIDATED = 0x6283;
    static final short AUTHENTICATION_FAILED_WARNING = 0x6300;
    static final short NO_SPECIFIC_DIAGNOSIS_ERROR = 0x6400;
    static final short REFERENCED_DATA_NOT_FOUND = 0x6A88;

	private static byte[] b = null;

    OPSystem() {

    }

    /**
    * This method returns the life cycle state of the selected application.
    * The Card Manager must find the AID of the calling applet by searching
    * for its entry in the Card Registry. The applet state variable is returned.
    *
    * @return Applet state variable
    * @see #APPLET_INSTALLED
    * @see #APPLET_SELECTABLE
    * @see #APPLET_PERSONALIZED
    * @see #APPLET_BLOCKED
    */
    public static byte getCardContentState() {
    	return VN.native_OP_getCardContentState();
    }

    /**
    * This method returns the life cycle state of the Card Manager.
    *
    * @return Card Manager state variable
    *
    * @see #CARD_OP_READY
    * @see #CARD_INITIALIZED
    * @see #CARD_SECURED
    * @see #CARD_CM_LOCKED
    * @see #CARD_TERMINATED
    */
    public static byte getCardManagerState() {
	    return VN.native_OP_getCardState();
    }

    /**
    * This method returns the card's production life cycle data. The calling applet passes
    * a handle to the APDU object and an offset where the CPLC data shall be placed.
    *
    * @param theAPDU APDU	javacard.framework.APDU
    * @param apdu_offset    Offset within an APDU buffer
    * @param cplc_offset   	Offset within the CPLC buffer
    * @param length short	The length of the data to be placed into the buffer
    * @exception javacard.framework.CardRuntimeException
    *            The exception is thrown as a result of a decryption failure.
    */
    public static void getCPLCData(APDU apdu, short apdu_offset, short cplc_offset, short length) {
	    VN.native_OP_201_getCPLCData_CT();
    }

    /**
    * This method returns the PIN tries remaining for the retry counter of the Card Global PIN.
    *
    * @return byte - Tries Remaining counter
    */
    public static byte getTriesRemaining() {
        return VN.native_OP_getCVMTriesRemaining();
    }

	private final static byte SD_SCEURITYDOMAIN = (byte) 0x44;

    /**
    * This method returns a handle of the application's associated Security Domain.
    * The handle of the applet's Security Domain object is returned back back to the calling applet.
    * The Card Manager needs to determine the AID of the calling applet, and then locate its Security Domain.
    *
    * @return ProviderSecurityDomain
    */
	public static ProviderSecurityDomain getSecurityDomain()
	{
    	if (b!=null)
    	{
    		b[(short)0] = SD_SCEURITYDOMAIN;
			Object o = VN.native_OP_getSecureChannel(b);
			try{
/***
				switch (b[0]){
					case 1:
						return (ProviderSecurityDomain)(JCSystem.getAppletShareableInterfaceObject((AID)o, SD_SCEURITYDOMAIN));
					case 2:
						return (ProviderSecurityDomain)o;
				}
***/
				return (ProviderSecurityDomain)o;
			}catch(Exception e){}
	     	return null;
	    }
   		// Init
   		b = new byte[1];
    	VN.native_OP_201_setISD(new ISDSecurityDomain());
    	return null;
    }

    /**
    * This method allows an application to change its own life cycle state.
    * It is used by an applet to change its own life cycle state. The Card Manager determines
    * the AID of the calling entity and modifies the corresponding entry in the Card Registry.
    * The Card Manager is also responsible for enforcing the state transition rules defined.
    *
    * @return boolean
    * @param new_state byte
    *
    * @see #APPLET_SELECTABLE
    * @see #APPLET_PERSONALIZED
    * @see #APPLET_BLOCKED
    */
    public static boolean setCardContentState (byte new_state) {
        return VN.native_OP_setCardContentState_CT();
    }

    /**
    * This method allows an applet to lock the card. This can be done in case of a security threat.
    * If the calling applet has been authorized to perform this operation and the operation is
    * successful, this method returns TRUE, otherwise FALSE. This operation is reversible.
    *
    * @return boolean
    */
    public static boolean lockCardManager() {
	    return VN.native_OP_lockCard();
    }

    /**
    * This method allows an application to terminate the card.
    * If allows an applet to request the irreversible termination of the Card Manager's
    * functionality. The card becomes inoperable. If the calling applet has been
    * authorized to perform this operation, this method returns TRUE, otherwise FALSE.
    *
    * @return boolean
    */
    public static boolean terminateCardManager() {
	    return VN.native_OP_terminateCard();
    }

    /**
    * This method is used to initialize the Card Global PIN. The length of the PIN is retrieved
    * from thePin structure. If the calling applet has been authorized to perform this operation
    * and the operation is successful, this method returns TRUE, otherwise FALSE.
    *
    * @return boolean
    * @param theAPDU APDU	javacard.framework.APDU
    * @param offset short	Offset within an APDU buffer
    */
    public static boolean setPin(APDU apdu, short offset) {
    	try {
    		byte[] buff = apdu.getBuffer();
    		short length = (short)(buff[offset] & 0x0F);
    		return VN.native_OP_getCVM_CT().update(buff, (short)(offset+1), (byte)((short)(length+1)/2), CVM.FORMAT_BCD);
	    } catch (Exception e)
	    {
		}
		return false;
    }

    /**
    * This method allows an application to check the validity of a PIN.
    * It returns TRUE if the supplied PIN matches the Card Global PIN, and FALSE otherwise.
    *
    * @return boolean
    */
    public static boolean verifyPin(APDU apdu, short offset) {
    	try
    	{
    		byte[] buff = apdu.getBuffer();
    		short length = (short)(buff[offset] & 0x0F);
    		return (VN.native_OP_getCVM_CT().verify(buff, (short)(offset+1), (byte)((short)(length+1)/2), CVM.FORMAT_BCD)==CVM.CVM_SUCCESS);
	    } catch (Exception e)
	    {
		}
		return false;
	}

	/**
    * This method sets the historical bytes contained in the ATR (Answer To Reset). The sequence of
    * bytes will be set on a subsequent power-up or reset. See ISO7816-3 for more information on ATR.
    * Only the implicitly selectable application may invoke this method, otherwise false is returned.
    *
    * @return boolean
    * @param buffer byte[]
    * @param offset short
    * @param length byte
    */

	public static boolean setATRHistBytes(byte[] buffer, short offset, byte length) {
        return VN.native_OP_setATRHistBytes_CT();
	}

}